最新版Mybatis

您所在的位置:网站首页 mybatis model 最新版Mybatis

最新版Mybatis

2023-08-23 10:15| 来源: 网络整理| 查看: 265

前言:现实开发中我们常常会遇到这样一种情况:技术经理要求开发人员创建的每一个表都要有一些公共字段:创建者id、更新者id、创建及更新时间、逻辑删除字段、租户字段等等。

而我们在新增记录或者更新记录的时候往往要频繁处理这些字段,而抽离出来的话,与持久层框架的结合又很不舒服。好在mybatis-plus为我们提供了很好用的自动填充和逻辑删除支持。

思路

上次有朋友说他们平时对于持久层的实体类对象,会把公共字段抽出来当一个父类,而不是每一个实体类中都有这些字段,mybatis-plus支持了抽出父类的模式,也支持后面一种模式(笔者用的就是后面一种),因此本篇会两种都讲,主要以前者为主。

mybatis-plus实现自动填充和逻辑删除的逻辑大致是:

实体类中对需要自动填充和逻辑删除的字段做标记配置(交给公共类去实现或者交给代码生成器去实现) 配置全局的自动填充实现代码 配置全局的逻辑删除实现配置 业务代码不需要编写任何公共字段的逻辑 公共Entity方式 表字段

首先看一下数据库中涉及的公共字段,逻辑删除一般用tinyint或者boolean(如果支持的话)

image.png

对于创建时间和创建人,要实现执行insert语句时自动添加创建信息 对于更新时间和更新人,要实现执行update语句时自动添加更新信息(如果要创建时也添加也可以) 创建数据时自动添加逻辑删除值为false 删除数据时将记录的逻辑删除值设置为true 所有查询操作以及删改操作的范围一律默认加上逻辑删除值为false 符合ActiveRecord模式的entity公共父类

上文讲过entity是支持ActiveRecord模式的,放在java项目中,简单来说就是可以直接通过实体来进行增删改查操作,即:

mapper.insert(entity) ↓↓↓↓↓↓ entity.insert()

而如果我们在代码生成器中设置activeRecord模式为true,那么生成的entity类就会集成mybatis-plus的com.baomidou.mybatisplus.extension.activerecord.Model类。 那么如果我们要给所有的entity设置公共父类用以拓展(比如公共字段这些),就需要继承这个Model类。 即,mybatis-plus的Model为最上级,然后是中间的公共父类,最后是一个个的业务Entity类。 当然,要是不想使用activeRecord模式也就不需要继承Model了,直接一个简单的java类当公共父类即可。 下面是示例的公共entity类代码:

import com.baomidou.mybatisplus.annotation.FieldFill; import com.baomidou.mybatisplus.annotation.TableField; import com.baomidou.mybatisplus.annotation.TableLogic; import com.baomidou.mybatisplus.extension.activerecord.Model; import lombok.Getter; import lombok.Setter; import java.io.Serializable; import java.time.LocalDateTime; /** * @ClassName EntityCommon * @Description 公共entity类 * @Author Chenyongyu * @Date 2022/1/12 15:19 * @Version 1.0 **/ @Getter @Setter public abstract class EntityCommon extends Model { @TableField(value = "create_id", fill = FieldFill.INSERT) // 创建人id private Long createId; @TableField(value = "create_time", fill = FieldFill.INSERT) // 创建时间 private LocalDateTime createTime; @TableField(value = "update_id", fill = FieldFill.UPDATE) // 更新人id private Long updateId; @TableField(value = "update_time", fill = FieldFill.UPDATE) // 更新时间 private LocalDateTime updateTime; // 逻辑删除 @TableLogic @TableField(value = "deleted") private boolean deleted; public abstract Serializable pkVal(); } Model类中的泛型T用来传递具体实体entity类,这样mybatis-plus才能给持久层传递此类对应的表信息等,因此泛型信息需要层层继承 抽象方法pkVal,具体实体类需要实现此方法,mybatis-plus通过此方法找到实体的主键,比如区分插入还是更新等逻辑 @TableField + fill注解标记自动填充的字段,其中value为对应表字段,fill为填充模式,有INSERT、UPDATE、INSERT_UPDATE这几种模式。比如更新时间这个字段,在新增记录时,有的人习惯也加上更新时间,有的人习惯更新时间为空,这就是UPDATE和INSERT_UPDATE的区别。 @TableLogic标记逻辑删除字段 逻辑删除的配置

因为逻辑删除既支持boolean型,也支持字符串、数字型甚至是时间类型,所以我们需要配置删除状态和未删除状态对应的数据库值。这里mysql我们使用的数据库类型为tinyint(1),所以逻辑删除值可以用1与0表示。具体需要配置在application.yaml文件中:

mybatis-plus: #...省略其他配置 global-config: db-config: logic-delete-field: deleted # 全局逻辑删除的实体字段名 logic-delete-value: 1 # 逻辑已删除值(默认为 1) logic-not-delete-value: 0 # 逻辑未删除值(默认为 0)

这样配置的效果是:在新增记录时,默认会给deleted字段赋值0,涉及查询时(update等操作默认的where条件也算),会默认添加deleted=0的条件,即逻辑未删除的记录。执行delete语句时,不会删除记录,只会把记录对应的deleted属性设置为1。

代码生成器

最后我们要修改代码生成器中关于entity的策略配置。

一方面,要设置entity的公共父类 另一方,要设置entity生成忽略的字段,即我们分离出去的updateTime,deleted等。 .strategyConfig(builder -> { builder .addInclude("table_4_mp") // 跳过视图的生成 .enableSkipView() .entityBuilder() // (重要)主键模式,这里设置自动模式,配合mysql的自增主键 .idType(IdType.AUTO) // entity文件名,这里配置后面统一加Entity后缀 .formatFileName("%sEntity") // activeRecord模式,使用上来说就是可以直接在entity对象上执行insert、update等操作 .enableActiveRecord() // ###########修改点是下面两条############## // 公共父类 .superClass(EntityCommon.class) // 忽略的列 .addIgnoreColumns("create_time","create_id","update_time","update_id","deleted") .build(); })

我们看一眼生成的类:

image.png

编写自动填充逻辑

这一步是实现mybatis-plus自动填充的关键一步,即自定义自动填充具体的业务实现。

新建一个springbean继承MetaObjectHandler接口 实现insertFill和updateFill方法 编写每个字段具体的业务实现 @Component public class AutoFillMetaObjectHandler implements MetaObjectHandler { @Override public void insertFill(MetaObject metaObject) { // 创建时间,取当前时间,也可以自定义 this.strictInsertFill(metaObject, "createTime", LocalDateTime.class, LocalDateTime.now()); // 创建人id,这个看自身业务如何获取,我这里是获取的保存在上下文(ThreadLocal)中的用户id this.strictInsertFill(metaObject, "createId", Long.class, UserContext.getUserInfo().get().getUserId()); } @Override public void updateFill(MetaObject metaObject) { // 更新时间,取当前时间,也可以自定义 this.strictUpdateFill(metaObject, "updateTime", LocalDateTime.class, LocalDateTime.now()); // 更新人id,这个看自身业务如何获取,我这里是获取的保存在上下文(ThreadLocal)中的用户id this.strictUpdateFill(metaObject, "updateId", Long.class, UserContext.getUserInfo().get().getUserId()); } }

这里稍微说一下strictInsertFill方法和strictUpdateFill方法

MetaObjectHandler strictInsertFill(MetaObject metaObject, String fieldName, Class fieldType, E fieldVal)

四个参数分别是:

透传的metaObject对象,即用来插入或修改的表实体类对象,可以在这里读取或修改 字段名,是类字段名,不是表字段名 字段类型,java类型 填充的值,这个就是最关键的我们想要自动填充的业务值,比如当前时间、当前会话代表的用户id、当前所在环境等等 验证

到这里,自动填充和逻辑删除的设置就做好了,我们编写一些代码来测试一下:

// 模拟会话状态,真正业务环境会在调用controller接口时往会话中加入当前用户id UserInfo userInfo = new UserInfo(); userInfo.setUserId(34112398L); UserContext.getUserInfo().set(userInfo); // 直接用new的实体来insert Table4MpEntity table4MpEntity = new Table4MpEntity(); table4MpEntity.setName("辣椒儿"); table4MpEntity.setAge(28); table4MpEntity.insert(); System.out.println("createTime:"+table4MpEntity.getCreateTime()); System.out.println("updateTime:"+table4MpEntity.getUpdateTime()); // 修改年龄 table4MpEntity.setAge(29); table4MpEntity.updateById(); System.out.println("createTime:"+table4MpEntity.getCreateTime()); System.out.println("updateTime:"+table4MpEntity.getUpdateTime()); // 删除 table4MpEntity.deleteById(); // 再查询 Table4MpEntity table4MpEntitySearch = table4MpMapper.selectById(table4MpEntity.getId()); System.out.println(table4MpEntitySearch == null);

结果:

createTime:2022-01-17T16:28:33.139 updateTime:null createTime:2022-01-17T16:28:33.139 updateTime:2022-01-17T16:28:35.051 true

image.png

自动填充和逻辑删除都是有效的。

独立entity方式

最后再介绍一下独立entity,即不适用公共的父类的方式,这种方式下createTime、updateId、deleted等在各自的entity类内部,包括各自的注解等。 这种情况下如果手动编写注解,则会面临下次执行代码生成器时自定义的代码被顶掉的问题。 好在mybatis-plus在代码生成器中为我们提供了相关设置:

.strategyConfig(builder -> { builder .addInclude("table_4_mp") // 跳过视图的生成 .enableSkipView() .entityBuilder() // (重要)主键模式,这里设置自动模式,配合mysql的自增主键 .idType(IdType.AUTO) // entity文件名,这里配置后面统一加Entity后缀 .formatFileName("%sEntity") // activeRecord模式,使用上来说就是可以直接在entity对象上执行insert、update等操作 .enableActiveRecord() // 添加tableField注解 .enableTableFieldAnnotation() // 自动填充字段 .addTableFills(Arrays.asList( new Column("create_time", FieldFill.INSERT), new Column("create_id", FieldFill.INSERT), new Column("update_time", FieldFill.UPDATE), new Column("update_id", FieldFill.UPDATE) )) // 逻辑删除字段 .logicDeleteColumnName("deleted") .build(); })

这里主要修改了enableTableFieldAnnotation、addTableFills、logicDeleteColumnName这三个设置,指定逻辑删除的字段和自动填充的字段。生成后的entity效果:

image.png

其他诸如自动填充业务逻辑的配置、逻辑删除的配置文件设置等都是一样的。



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3